package com.gwsoft.mm.file;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.gwsoft.wimpframework.bean.ServiceProperties;
import com.gwsoft.wimpframework.util.DateUtil;

public class FileUpLoad2 {
	private static final Log logger = LogFactory.getLog(FileUpLoad2.class);
	//默认上传限制为100M大小
	private static final long DEFAULT_MAX_SIZE = 104857600;
	public static final int UPLOAD_STATUS_NORMAL = 1;
	public static final int UPLOAD_STATUS_ERROR = 0;
	//	//上传的文件的新文件名
	//	private String newFileName;
	//	//上传文件后缀
	//	private String fileSuffix;
	//	//文件大小
	//	private long fileSizes;

	//从上传表单中获取的参数
	private final ServiceProperties properties = new ServiceProperties();
	//上传文件保存的路径
	private String path;

	//过滤的后缀名(符合条件的后缀名才能上传)
	private Collection<String> filterSuffix;
	//要保存到ServiceProperties中的参数名
	//	private Collection<String> propertiesField;

	private final HttpServletRequest request;
	private final HttpServletResponse response;
	//错误消息
	private String errorMessage;
	//最大允许单个文件上传大小
	private long maxSize;
	//上传状态
	private long status = UPLOAD_STATUS_NORMAL;

	private final List<File> files = new CopyOnWriteArrayList<File>();

	private boolean changeFileName = true;
	
	public List<DiskFileItem> pub_items;

	public FileUpLoad2(HttpServletRequest request, HttpServletResponse response) {
		this.request = request;
		this.response = response;
		try {
			this.request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		this.response.setCharacterEncoding("UTF-8");
	}

	/**
	 * 初始化
	 * 从FORM表单中得到表单参数和参数的值
	 * 从FORM表单中得到要上传的文件
	 */
	public void init() {

		try {
			FileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
			if (this.maxSize == 0) {
				this.maxSize = DEFAULT_MAX_SIZE;
			}
			upload.setFileSizeMax(this.maxSize);
			@SuppressWarnings("unchecked")
			List<DiskFileItem> items = upload.parseRequest(request);
			pub_items=items;
			int fileNum=0;//用于当上传文件大于1时加后缀以避免生成的文件名一样
			for (DiskFileItem item : items) {
				if (item.isFormField()) {
					String formFieldName = item.getFieldName();
					this.properties.addProperty(formFieldName, item.getString("UTF-8"));
				} else {
					if (StringUtils.isNotBlank(item.getName())) {
						fileNum++;
						String fileName = item.getName();
						if (changeFileName) {
                            if(fileNum>1){
   							 fileName = (Long.parseLong(DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"))+fileNum) + "."
								+ FilenameUtils.getExtension(item.getName());
                            }else{
							 fileName = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") + "."
									+ FilenameUtils.getExtension(item.getName());
                            }
							
						} else {
							fileName = FilenameUtils.getBaseName(item.getName()) + "-"
									+ DateFormatUtils.format(new Date(), "HHmmssSSS") + "."
									+ FilenameUtils.getExtension(item.getName());
						}

						File file = saveFile(item,
								"/tmp/" + DateUtil.getDateFormatString(new Date(), "yyyyMMdd") + "/", fileName);
						this.properties.addProperty(item.getFieldName(), file.getPath());
						this.files.add(file);
					}
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public synchronized void upLoad(File file, String newFileName) {
		//判断文件大小
		if (file.length() > maxSize) {
			errorMessage = "文件大于" + (maxSize / 1024 / 1024) + "M";
			logger.error(errorMessage);
			this.status = UPLOAD_STATUS_ERROR;
			return;
		}
		//判断文件后缀是否允许
		String fileSuffix = FilenameUtils.getExtension(file.getName());
		if (StringUtils.isBlank(fileSuffix)) {
			errorMessage = "文件没有后缀，上传失败";
			this.status = UPLOAD_STATUS_ERROR;
			return;
		}
		if (filterSuffix != null) {
			logger.debug("suffix=" + filterSuffix);
			logger.debug("fileSuffix=" + fileSuffix);

			if (filterSuffix.contains(fileSuffix)) {
				saveFile(file, path, newFileName + "." + fileSuffix);
			} else {
				errorMessage = "后缀名不匹配，无法上传";
				this.status = UPLOAD_STATUS_ERROR;
				logger.debug(errorMessage);
			}
		} else {
			saveFile(file, path, newFileName + "." + fileSuffix);
		}
	}

	//保存文件
	private File saveFile(DiskFileItem item, String path, String fileName) {

		new File(path).mkdirs();
		File uploadFile = new File(path, fileName);
		try {
			logger.debug("上传文件" + uploadFile.getName());
			if (this.status == UPLOAD_STATUS_NORMAL) {
				/*
				//如果是文本文件，转换成UTF-8编码格式
				if ("text/html".equals(item.getContentType())) {
					//				if (uploadFile.getName().endsWith("txt")) {
					InputStream in = null;
					FileOutputStream out = null;
					try {
						in = item.getInputStream();
						out = new FileOutputStream(uploadFile);

						IOUtils.copy(new InputStreamReader(in, "GBK"), out, "UTF-8");
					} finally {
						if (in != null) {
							in.close();
						}
						if (out != null) {
							out.close();
						}
					}
				} else {
					//否则直接写入文件
					 
					item.write(uploadFile);
				}
				*/
				item.write(uploadFile);
			}
		} catch (Exception e) {
			logger.error(e);
			this.setErrorMessage("上传文件失败");
			this.status = UPLOAD_STATUS_ERROR;
		}
		return uploadFile;

	}

	// 保存文件
	private void saveFile(File file, String path, String fileName) {
		File newFile = new File(path + fileName);
		try {
			FileUtils.copyFile(file, newFile);
			//			file.delete();
		} catch (IOException e) {
			logger.error(e);
			this.status = UPLOAD_STATUS_ERROR;
			this.errorMessage = "上传文件失败";

		}
	}

	// 删除文件
	public static void deleteFile(String filePath) {
		File deleteFile = new File(filePath);
		deleteFile.deleteOnExit();
	}

	public void writeToClient() {
		logger.info(this.getErrorMessage());
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
			String script = "<SCRIPT language = JavaScript type=text/javascript >window.parent.fnsetuppicid('"
					+ this.getErrorMessage() + "','" + status + "');</SCRIPT >";
			out.print(script);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}

	}

	public ServiceProperties getProperties() {
		return (ServiceProperties) properties.clone();
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public synchronized Collection<String> getFilterSuffix() {
		return filterSuffix;
	}

	public synchronized void setFilterSuffix(Collection<String> filterSuffix) {
		this.filterSuffix = filterSuffix;
	}

	//	public Collection<String> getPropertiesField() {
	//		return propertiesField;
	//	}
	//
	//	public void setPropertiesField(Collection<String> propertiesField) {
	//		this.propertiesField = propertiesField;
	//	}

	public synchronized String getErrorMessage() {
		return String.valueOf(errorMessage);
	}

	public synchronized void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

	public void setMaxSize(long maxSize) {
		this.maxSize = maxSize;
	}

	public HttpServletRequest getRequest() {
		return request;
	}

	public HttpServletResponse getResponse() {
		return response;
	}

	public long getStatus() {
		return Long.valueOf(status);
	}

	public void setStatus(long status) {
		this.status = status;
	}

	public List<File> getFiles() {
		return files;
	}

	public void setChangeFileName(boolean changeFileName) {
		this.changeFileName = changeFileName;
	}

}
